package tcinert;
/*
 * Diplomova Prace: Vyuziti embedded modulu pro monitoring zivotnich funkci 
 *                  pacienta
 * Trida: Jadro.java
 * Autor: Tomas Cinert
 * Vytvoreno: 14.4.2012
 */

import com.siemens.icm.io.CommConnectionControlLinesListener;
import java.util.Calendar;
import java.util.Date;
import javax.microedition.rms.RecordStoreException;
import com.siemens.icm.io.ATCommandFailedException;
import com.siemens.icm.io.CommConnectionControlLines;
import java.io.InputStream;
import java.io.IOException;
import javax.microedition.io.Connector;
import tcinert.Stav;

/**
 * Trida Jadro - hlavni program, ktery ma na starosti obsluhu behu(inicializace,
 * cteni dat, obsluha databaze, upload dat)
 * @author Tomas Cinert
 * @version 0.9.1
 */
public class Jadro implements Runnable{
    /* Aktualni cas pro log a pro zapis do DB*/
    Calendar datum;
    /* Seriova komunikace*/
    CommConnectionControlLines spojeni;
    CommConnectionControlLinesListener comListener;
    /* Programova cast */
    Inicializace init;
    Databaze databaze;
    Zaznam zaznam;
    /* Vlakna */
    Thread vlaknoHlavni=new Thread(this);
    Thread cteciVlakno=null;
    Thread uploadVlakno=null;
    /* Pomocne promenne*/
    int c;
    private boolean loop=true;
    int i=0;
    private int pocetChyb=0;
    String[][] data=null;
    Stav reset;
    String a=null;
    StringBuffer buffer;

    /**
     *Konstruktor
     * - inicalizuje veskere tridy a spousti vlakna (cteni dat a upload)
     **/
    public Jadro(Stav reset,Zaznam zaznam) {
        this.zaznam=zaznam;
        this.reset=reset;
        buffer=new StringBuffer();
        /* Program startuje */
        zaznam.zapis("Hlavni program startuje",typZapisu.Informativni);
        zaznam.zapis("Inicializace modemu",typZapisu.Informativni);
        /** Inicializace modemu */
        try {
            init=new Inicializace(reset);
            init.setPin(1);         // Pokud inciializace probehne v pohode, tak muzem jet dal
            zaznam.zapis("Inicializace modemu OK",typZapisu.Informativni);
        } catch (IllegalStateException ex) {
            zaznam.zapis("Inicializace modemu"+ex.toString(),typZapisu.Chybovy);
            reset.setStav(true);
        } catch(ATCommandFailedException ex){
            zaznam.zapis("Inicializace modemu"+ex.toString(),typZapisu.Chybovy);
            reset.setStav(true);
        }catch (IOException ex){
            zaznam.zapis("1. Inicializace portu"+ex.toString(),typZapisu.Chybovy);
            try {
                init.inicializacePort(); // zkusit znovu zapnout, cist nejakej citac chyb a pokud ani podruhy se nepodari, tak vypnout a poslat sms, obe logovat
                init.setPin(1);         // Pokud inciializace v druhym kole probehne v pohode, tak muzem jet dal
            } catch (IOException ex2) {
                zaznam.zapis("2.Inicializace portu"+ex.toString(),typZapisu.Chybovy);
                // Vypnout, reportovat a jit dal a zkusit comak
            }
        }
        /* Seriove spojeni */
        vlaknoCteni(false);
        if(!reset.getData()) {
            zaznam.zapis("Nemame data. Spoustime cteni znova",typZapisu.Chybovy);
            init.reset();
            vlaknoCteni(false);
            if(!reset.getData()) {
                zaznam.zapis("Podruhe nebyly prijata data. Prepiname na komunikace po SPI",typZapisu.Chybovy);
                chybaKomunikace();
            }
            
        } else {
            zaznam.zapis("Inicializace serioveho spojeni v poradku",typZapisu.Informativni);
            try {
                init.setPin(3);
                init.setPin(2);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        /* Inicializace Databaze */
        zaznam.zapis("Inicializace databaze",typZapisu.Informativni);
        try {
            databaze=new Databaze();
            zaznam.zapis("Inicializace databaze probehla v poradku.",typZapisu.Informativni);
            zaznam.zapis("Databaze obsahuje"+databaze.pocetZaznamu()+"zaznamu",typZapisu.Informativni);
            if((data=databaze.odeslano())!=null)
            {
                zaznam.zapis("Databaze obsahuje neodeslane zaznamy.",typZapisu.Informativni);
                vlaknoUpload();
                if(data!=null){
                    zaznam.zapis("Pokud odeslat podruhe.",typZapisu.Informativni);
                    vlaknoUpload();
                    if(data!=null){
                        zaznam.zapis("Data ani na podruhe nebyly odeslany. Upload olozen.",typZapisu.Chybovy);
                    }
                    else{
                        zaznam.zapis("Data na podruhe odeslany.",typZapisu.Informativni);
                    }
                }
                else{
                    zaznam.zapis("Data odeslany.",typZapisu.Informativni);
                }
                    
                
            }
        } catch (RecordStoreException ex) {
            zaznam.zapis("Databaze nebyla otevrena z duvodu:"+ex.toString(),typZapisu.Chybovy);
        }catch (Exception ex){
            zaznam.zapis("Problem s inicialiazaci databaze"+ex.toString(),typZapisu.Chybovy);
        }
        /* Opetovna inicializace serioveho spojeni */
        serioveSpojeni();
        
        
        
        
        
        
        
    }
    /**
     *Spousti vlakno
     **/
    public void start() {
        loop = true;
        zaznam.zapis("Hlavni program nabiha",typZapisu.Informativni);
        vlaknoHlavni.start();
    }
    
    /**
     *Metoda na zastaveni vlakna (pri zmacknuti tlacitka)
     **/
    public void stop() {
        loop = false;
        zaznam.zapis("Hlavni vlakno ukonceno",typZapisu.Informativni);
        try {
            vlaknoHlavni.join();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
    /**
     *Metoda na otevreni serioveho spojeni
     * - synchronizovana
     **/
    private synchronized void serioveSpojeni() {
        zaznam.zapis("Inicializace serioveho spojeni",typZapisu.Informativni);
        uzavreniSpojeni();      // pokud uz existuje, uzavreme
        try {
            spojeni = (CommConnectionControlLines) Connector.open("comm:COM0;baudrate=4800", Connector.READ_WRITE, true);
            comListener=new CommConnectionControlLinesListener(){
                public void DTRChanged(boolean SignalState) {
                    if(SignalState){
                        vlaknoCteni(true);
                        //databaze.zapisDB(System.currentTimeMillis(),upravaDat(0,4),upravaDat(6,9),upravaDat(10,14),testPadu()); 
                        // ATsend("AT+CFUN=1,0");
                    } else {
                        init.ATsend("AT+CFUN=9,0\r");
                    }
                }
            };
            spojeni.addListener(comListener);
            zaznam.zapis("Otvirame seriove spojeni",typZapisu.Informativni);
        } catch (IOException ex) {
            zaznam.zapis("Nepodarilo se nam otevrit seriove spojeni",typZapisu.Chybovy);
        }
        
        
    }
    /**
     *Vytvori cteci vlakno
     **/
    private synchronized void vlaknoCteni(boolean prijemDat) {
        serioveSpojeni();
        if(cteciVlakno!=null){
            cteciVlakno=null;
        }
        cteciVlakno=new Thread(new Spojeni(zaznam, buffer,spojeni,reset));
        cteciVlakno.start();
        try {
            cteciVlakno.join();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        if(prijemDat)
        {
            databaze.zapisDB(System.currentTimeMillis(),upravaDat(0,4),upravaDat(6,9),upravaDat(10,14),testPadu()); 
            init.ATsend("AT+CFUN=9,0\r");
        }
    }
    /**
     *Metoda na uzavreni spojeni
     **/
    private void uzavreniSpojeni() {
        try {
            if(spojeni!=null){
                comListener=null;
                spojeni.close();
            }
        } catch (IOException ex) {
            zaznam.zapis("Problem s uzavrenim spojeni:"+ex.toString(),typZapisu.Chybovy);
        }
    }
    /**
     *Metoda na tvorbu vlakna pro odeslani dat do vzdalene DB, provede kontrolu odeslani a nastaveni statusu
     **/
    private synchronized void vlaknoUpload()
    {
        zaznam.zapis("Provadime upload dat.",typZapisu.Informativni);
        reset.setData(false);
        uzavreniSpojeni();
        if(uploadVlakno!=null)
        {
            uploadVlakno=null;           
        }
        if(init.testSignalu())
        {
            try{
                uploadVlakno=new Thread(new Pripojeni(zaznam,data,reset));
                uploadVlakno.start();
                uploadVlakno.join();
            }catch(Exception ex){
                zaznam.zapis("Upload se nepovedl z nasledujiciho duvodu."+ex.toString(),typZapisu.Chybovy);
            }
        }
        else
        {
            zaznam.zapis("Neni dostupny signal. Upload odlozen",typZapisu.Chybovy);
        }
        if(reset.getData())
        {
            databaze.nastaveniOdeslano();
            reset.setStav(false);
        }
    }
    /**
     * Pokud selhalo spojeni s deskou
     **/
    private void chybaKomunikace() {
        init.poslaniSMS("Selhalo spojeni s deskou"); 
        zaznam.zapis("Pokus uzavrit seriove spojeni a otevreni SPI spojeni",typZapisu.Informativni);
        uzavreniSpojeni();
        otevreniSPI();      
    }
    
    
    
    /**
     *Metoda na inicializaci a otevreni SPI spojeni (alternativni komunikace)
     **/
    private void otevreniSPI() {
        init.otevritSPI();
        try {
            init.zmenaPinu(true);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }  // Udelat listener na AT^SPI .. chybu reportovat, domyslet tu chybu tam
    
    
    /**
     *Metoda na upravu dat prijatych
     **/
    public double upravaDat(int zacatek, int konec)
   {
       char[] pole = null;
       buffer.getChars(zacatek,konec,pole,0);
       return(Double.parseDouble((new String(pole))));
   }
    /**
     *Test zda na pad v datech
     **/
    public boolean testPadu()
    {
        if((buffer.charAt(16))=='A')
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    /**
     *Hlavni smycka
     * - cekame na prijem dat
     * - jednou za hodinu upload dat
     **/
    public void run() {
        zaznam.zapis("Hlavni program nabiha", typZapisu.Informativni);
        int i=0;
        
       
        
           init.ATsend("AT+CFUN=9,0\r");
           
            //zaznam.zapis("Uz nespime",typZapisu.Aktualizace);/*
          
               /* if(i==10)
                {
                    reset.setStav(true);
                }*/
                //zapis do databaze
            
            
            
            
            
            
            
        
    }
}